package com.gitee.liuzhi.framework.starter.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.gitee.liuzhi.framework.starter.base.constant.DateFormatConstant;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.Objects;
import java.util.TimeZone;

/**
 * Created by 2022/4/29/0029
 *
 * @author LiuZhi
 * @version V1.0
 * @description: 序列化工具类
 */
@Slf4j
public class SerializeUtils {

    public static final ObjectMapper OBJECT_MAPPER;

    static {
        OBJECT_MAPPER = new ObjectMapper();
        // 忽略在json字符串中存在，但是在java对象中不存在对应属性的情况
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 忽略空Bean转json的错误
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        // 允许不带引号的字段名称
        OBJECT_MAPPER.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES.mappedFeature(), true);

        // 允许单引号
        OBJECT_MAPPER.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);

        // allow int startWith 0
        OBJECT_MAPPER.configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature(), true);

        // 允许字符串存在转义字符：\r \n \t
        OBJECT_MAPPER.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);

        // 排除空值字段
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 使用驼峰式
        OBJECT_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE);

        // 使用bean名称
        OBJECT_MAPPER.enable(MapperFeature.USE_STD_BEAN_NAMING);

        // 所有日期格式都统一为固定格式
        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(DateFormatConstant.DATETIME_FORMAT));

        // TIME_ZONE_GMT8
        OBJECT_MAPPER.setTimeZone(TimeZone.getTimeZone(DateFormatConstant.TIME_ZONE_GMT8));
    }

    public static String serialize(Object obj) {
        Objects.requireNonNull(obj, "序列化对象不能为空!");
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException("序列化出错!");
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T deserialize(String str, Class<T> tClass) {
        Objects.requireNonNull(str, "反序列化字符不能为空!");
        Objects.requireNonNull(tClass, "反序列化对象类型不能为空!");
        if (tClass == String.class) {
            return (T) str;
        }
        try {
            return OBJECT_MAPPER.readValue(str, tClass);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException("反序列化出错!");
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T deserialize(String str, TypeReference<T> resultType) {
        Objects.requireNonNull(str, "反序列化字符不能为空!");
        Objects.requireNonNull(resultType, "反序列化对象类型不能为空!");
        if (resultType.getType() == String.class) {
            return (T) str;
        }
        try {
            return OBJECT_MAPPER.readValue(str, resultType);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException("反序列化出错!");
        }
    }

}
